<template>
  <div class="bpmn-container">
    <div class="header">
      <h2>{{ title }}</h2>
      <div class="controls">
        <el-button-group>
          <el-tooltip content="缩小视图" placement="bottom">
            <el-button :icon="ZoomOut" @click="zoomOut"/>
          </el-tooltip>
          <el-button>{{ Math.round(zoom * 100) }}%</el-button>
          <el-tooltip content="放大视图" placement="bottom">
            <el-button :icon="ZoomIn" @click="zoomIn"/>
          </el-tooltip>
          <el-tooltip content="重置视图" placement="bottom">
            <el-button :icon="Refresh" @click="resetZoom"/>
          </el-tooltip>
        </el-button-group>
      </div>
    </div>

    <div id="bpmn-canvas" ref="canvas"></div>

    <div v-if="loading" class="loading-overlay">
      <el-icon class="loading-icon">
        <Loading/>
      </el-icon>
    </div>

    <div v-if="activeNode" class="node-details">
      <h3>{{ activeNode.name || activeNode.id }}</h3>
      <div class="detail-row">
        <span class="label">ID:</span>
        <span class="value">{{ activeNode.id }}</span>
      </div>
      <div v-if="activeNode.approvers" class="detail-row">
        <span class="label">审批人:</span>
        <div class="approvers">
          <el-tag
              v-for="(approver, index) in activeNode.approvers"
              :key="index"
              class="approver-tag"
              size="small"
              type="success"
          >
            {{ approver }}
          </el-tag>
        </div>
      </div>
      <div class="detail-row">
        <span class="label">状态:</span>
        <el-tag :type="getStatusType(activeNode.status)">{{ activeNode.status }}</el-tag>
      </div>
      <div v-if="activeNode.startTime" class="detail-row">
        <span class="label">开始时间:</span>
        <span class="value">{{ formatDate(activeNode.startTime) }}</span>
      </div>
      <div v-if="activeNode.endTime" class="detail-row">
        <span class="label">结束时间:</span>
        <span class="value">{{ formatDate(activeNode.endTime) }}</span>
      </div>
      <div v-if="activeNode.duration" class="detail-row">
        <span class="label">耗时:</span>
        <span class="value">{{ activeNode.duration }}</span>
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref, onMounted, onBeforeUnmount} from 'vue'
import {ElButton, ElButtonGroup, ElTooltip, ElTag, ElIcon, ElMessage} from 'element-plus'
import {ZoomIn, ZoomOut, Refresh, Loading} from '@element-plus/icons-vue'
import BpmnViewer from 'bpmn-js/dist/bpmn-viewer.production.min.js'
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'

// 响应式数据
const canvas = ref(null)
const bpmnViewer = ref(null)
const title = ref('流程预览')
const loading = ref(true)
const zoom = ref(1)
const activeNode = ref(null)
const nodeDetailsCache = ref({})

// 流程实例ID和定义ID（可以从props传入）
const processInstanceId = ref('proc_inst_456') // 示例流程实例ID

// 绘制凹字形虚线连接（无边框文字）
async function drawAllJumpLines(flowId) {
  try {
    // 获取跳转连线数据
    const jumpLines = [
      {
        "sourceId": "Task_1",
        "targetId": "Task_2",
        "type": 1,
        "label": "通过跳转"
      },
      {
        "sourceId": "Task_3",
        "targetId": "Task_1",
        "type": 2,
        "label": "驳回跳转"
      }
    ]

    // 高亮节点
    jumpLines.forEach(jumpLine => {
      const color = jumpLine.type === 1 ? '#52c41a' : '#f5222d'; // 1:绿色, 2:红色
      const label = jumpLine.label || (jumpLine.type === 1 ? '跳转' : '驳回');
      drawCurvedDashedConnection(jumpLine.sourceId, jumpLine.targetId, label, color)
    })
  } catch (error) {
    console.error('加载跳转连线失败:', error)
    ElMessage.error('加载跳转连线失败: ' + error.message)
  }
}

// 绘制凹字形虚线连接
// 绘制凹字形虚线连接
function drawCurvedDashedConnection(sourceId, targetId, labelText = '跳转', color = '#1890ff') {
  try {
    const canvasInstance = bpmnViewer.value.get('canvas')
    const elementRegistry = bpmnViewer.value.get('elementRegistry')

    const sourceElement = elementRegistry.get(sourceId)
    const targetElement = elementRegistry.get(targetId)

    if (!sourceElement || !targetElement) {
      throw new Error('无法找到源或目标元素')
    }

    // 获取元素位置
    const sourcePosition = canvasInstance.getAbsoluteBBox(sourceElement)
    const targetPosition = canvasInstance.getAbsoluteBBox(targetElement)

    // 计算连接点（从源元素右侧到目标元素左侧）
    const startX = sourcePosition.x + sourcePosition.width
    const startY = sourcePosition.y + sourcePosition.height / 2
    const endX = targetPosition.x
    const endY = targetPosition.y + targetPosition.height / 2

    // 计算控制点（形成凹字形）
    const controlOffset = 80 // 控制点偏移量，决定曲线弧度
    const controlX1 = startX + (endX - startX) * 0.3
    const controlY1 = startY + controlOffset
    const controlX2 = startX + (endX - startX) * 0.7
    const controlY2 = endY + controlOffset

    // 计算中间点位置（用于放置文字）
    const midX = (startX + endX) / 2
    const midY = (startY + endY) / 2 + controlOffset

    // 获取SVG容器
    const svg = canvasInstance._svg

    // 创建凹字形虚线路径
    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
    path.setAttribute('d', `M ${startX} ${startY}
                          C ${controlX1} ${controlY1},
                            ${controlX2} ${controlY2},
                            ${endX} ${endY}`)
    path.setAttribute('stroke', color) // 使用传入的颜色
    path.setAttribute('stroke-width', '2')
    path.setAttribute('stroke-dasharray', '5,3')
    path.setAttribute('fill', 'none')
    path.setAttribute('class', 'custom-curved-line')
    path.setAttribute('marker-end', 'url(#arrowhead-' + color.replace('#', '') + ')')

    // 创建箭头标记（如果尚未创建）
    const markerId = 'arrowhead-' + color.replace('#', '');
    if (!document.getElementById(markerId)) {
      const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')
      const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker')
      marker.setAttribute('id', markerId)
      marker.setAttribute('markerWidth', '10')
      marker.setAttribute('markerHeight', '7')
      marker.setAttribute('refX', '8')
      marker.setAttribute('refY', '3.5')
      marker.setAttribute('orient', 'auto')

      const arrow = document.createElementNS('http://www.w3.org/2000/svg', 'path')
      arrow.setAttribute('d', 'M0,0 L10,3.5 L0,7 Z')
      arrow.setAttribute('fill', color) // 使用传入的颜色

      marker.appendChild(arrow)
      defs.appendChild(marker)
      svg.insertBefore(defs, svg.firstChild)
    }

    // 创建文字标签（无背景框）
    const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
    text.setAttribute('x', midX)
    text.setAttribute('y', midY + 5)
    text.setAttribute('text-anchor', 'middle')
    text.setAttribute('font-size', '12')
    text.setAttribute('fill', color) // 使用传入的颜色
    text.setAttribute('class', 'connection-label')
    text.textContent = labelText

    // 添加到SVG（只添加路径和文字）
    svg.appendChild(path)
    svg.appendChild(text)

    console.log(path)
    console.log(text)

    return {path, text}

  } catch (error) {
    console.error('绘制凹字形连接失败:', error)
    ElMessage.error('绘制凹字形连接失败: ' + error.message)
  }
}

// 初始化流程图
onMounted(async () => {
  bpmnViewer.value = new BpmnViewer({
    container: canvas.value,
    height: '100%',
    width: '100%'
  })

  try {

    // 导入XML
    await bpmnViewer.value.importXML("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bpmn:definitions xmlns:bpmn=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" \n  xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" \n  xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" \n  xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\" \n  id=\"Definitions_1\" targetNamespace=\"http://bpmn.io/schema/bpmn\">\n  \n  <bpmn:process id=\"Process_1\" isExecutable=\"false\">\n    <bpmn:startEvent id=\"StartEvent_1\" />\n    <bpmn:sequenceFlow id=\"Flow_1\" sourceRef=\"StartEvent_1\" targetRef=\"Task_1\" />\n    <bpmn:userTask id=\"Task_1\" name=\"提交申请\" />\n    <bpmn:sequenceFlow id=\"Flow_2\" sourceRef=\"Task_1\" targetRef=\"Task_2\" />\n    <bpmn:userTask id=\"Task_2\" name=\"经理审批\" />\n    <bpmn:sequenceFlow id=\"Flow_3\" sourceRef=\"Task_2\" targetRef=\"ExclusiveGateway_1\" />\n    <bpmn:exclusiveGateway id=\"ExclusiveGateway_1\" />\n    <bpmn:sequenceFlow id=\"Flow_4\" sourceRef=\"ExclusiveGateway_1\" targetRef=\"Task_3\" />\n    <bpmn:userTask id=\"Task_3\" name=\"财务处理\" />\n    <bpmn:sequenceFlow id=\"Flow_5\" sourceRef=\"Task_3\" targetRef=\"EndEvent_1\" />\n    <bpmn:endEvent id=\"EndEvent_1\" />\n  </bpmn:process>\n  \n  <bpmndi:BPMNDiagram id=\"BPMNDiagram_1\">\n    <bpmndi:BPMNPlane id=\"BPMNPlane_1\" bpmnElement=\"Process_1\">\n      <bpmndi:BPMNShape id=\"_BPMNShape_StartEvent_1\" bpmnElement=\"StartEvent_1\">\n        <dc:Bounds x=\"179\" y=\"159\" width=\"36\" height=\"36\" />\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape id=\"Activity_1di\" bpmnElement=\"Task_1\">\n        <dc:Bounds x=\"260\" y=\"137\" width=\"100\" height=\"80\" />\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape id=\"Activity_2di\" bpmnElement=\"Task_2\">\n        <dc:Bounds x=\"440\" y=\"137\" width=\"100\" height=\"80\" />\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape id=\"Gateway_1di\" bpmnElement=\"ExclusiveGateway_1\">\n        <dc:Bounds x=\"620\" y=\"152\" width=\"50\" height=\"50\" />\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape id=\"Activity_3di\" bpmnElement=\"Task_3\">\n        <dc:Bounds x=\"740\" y=\"137\" width=\"100\" height=\"80\" />\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape id=\"EndEvent_1di\" bpmnElement=\"EndEvent_1\">\n        <dc:Bounds x=\"900\" y=\"159\" width=\"36\" height=\"36\" />\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNEdge id=\"Flow_1_di\" bpmnElement=\"Flow_1\">\n        <di:waypoint x=\"215\" y=\"177\" />\n        <di:waypoint x=\"260\" y=\"177\" />\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge id=\"Flow_2_di\" bpmnElement=\"Flow_2\">\n        <di:waypoint x=\"360\" y=\"177\" />\n        <di:waypoint x=\"440\" y=\"177\" />\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge id=\"Flow_3_di\" bpmnElement=\"Flow_3\">\n        <di:waypoint x=\"540\" y=\"177\" />\n        <di:waypoint x=\"620\" y=\"177\" />\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge id=\"Flow_4_di\" bpmnElement=\"Flow_4\">\n        <di:waypoint x=\"670\" y=\"177\" />\n        <di:waypoint x=\"740\" y=\"177\" />\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge id=\"Flow_5_di\" bpmnElement=\"Flow_5\">\n        <di:waypoint x=\"840\" y=\"177\" />\n        <di:waypoint x=\"900\" y=\"177\" />\n      </bpmndi:BPMNEdge>\n    </bpmndi:BPMNPlane>\n  </bpmndi:BPMNDiagram>\n</bpmn:definitions>")

    // 设置高亮
    setHighlights(["Task_1", "Task_2"],
        ["Flow_1", "Flow_2"])

    // 绑定节点事件
    bindNodeEvents()

    // 绘制带箭头的虚线连接并添加文字
    await drawAllJumpLines(processInstanceId.value);
    // drawCurvedDashedConnection('Task_1', 'Task_2', '跳转')

    // 调整视口
    resetZoom()

    title.value = `流程预览 - 员工报销流程`
  } catch (error) {
    console.error('加载流程图失败:', error)
    ElMessage.error('加载流程图失败: ' + error.message)
  } finally {
    loading.value = false
  }
})

// 清理资源
onBeforeUnmount(() => {
  if (bpmnViewer.value) {
    bpmnViewer.value.destroy()
  }
})

// 设置节点高亮
function setHighlights(nodeIds, flowIds) {
  if (!bpmnViewer.value) return

  const canvas = bpmnViewer.value.get('canvas')

  // 高亮节点
  nodeIds.forEach(nodeId => {
    canvas.addMarker(nodeId, 'highlight-node')
  })

  // 高亮连线
  flowIds.forEach(flowId => {
    canvas.addMarker(flowId, 'highlight-flow')
  })

  // 高亮网关标记
  const elements = bpmnViewer.value.get('elementRegistry').getAll()
  elements.forEach(element => {
    if (element.type === 'bpmn:ExclusiveGateway') {
      canvas.addMarker(element.id, 'highlight-gateway')
    }
  })
}

// 绑定节点事件
function bindNodeEvents() {
  if (!bpmnViewer.value) return

  const eventBus = bpmnViewer.value.get('eventBus')

  // 节点鼠标悬停事件
  eventBus.on('element.hover', async (event) => {
    try {
      const nodeId = event.element.id

      // 只处理任务节点
      if (event.element.type.includes('Task')) {
        // 检查缓存
        if (nodeDetailsCache.value[nodeId]) {
          activeNode.value = nodeDetailsCache.value[nodeId]
          return
        }

        // // 获取节点详情
        // const details = await getNodeDetails(processInstanceId.value, nodeId)
        //
        // // 缓存结果
        // nodeDetailsCache.value[nodeId] = details
        //
        // // 显示节点详情
        // activeNode.value = {
        //   id: nodeId,
        //   name: event.element.name || event.element.type.split(':')[1],
        //   ...details
        // }
      }
    } catch (error) {
      console.error('处理节点悬停事件失败:', error)
      ElMessage.error('获取节点信息失败: ' + error.message)
    }
  })

  // 节点鼠标离开事件
  eventBus.on('element.out', () => {
    activeNode.value = null
  })
}

// 获取状态标签类型
function getStatusType(status) {
  switch (status) {
    case '已完成':
      return 'success'
    case '进行中':
      return 'warning'
    case '未开始':
      return 'info'
    default:
      return ''
  }
}

// 格式化日期
function formatDate(dateString) {
  if (!dateString) return 'N/A'
  const date = new Date(dateString)
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  })
}

// 视图控制
function zoomIn() {
  if (zoom.value < 3) {
    zoom.value += 0.1
    bpmnViewer.value.get('canvas').zoom(zoom.value)
  }
}

function zoomOut() {
  if (zoom.value > 0.2) {
    zoom.value -= 0.1
    bpmnViewer.value.get('canvas').zoom(zoom.value)
  }
}

function resetZoom() {
  zoom.value = 1
  bpmnViewer.value.get('canvas').zoom('fit-viewport')
}
</script>

<style scoped>
@import '@/styles/flowable.css';

.bpmn-container {
  position: relative;
  height: 100%;
  width: 100%;
}

#bpmn-canvas {
  height: calc(100% - 60px);
  width: 100%;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.loading-icon {
  font-size: 40px;
  color: #409eff;
  animation: rotating 2s linear infinite;
}

@keyframes rotating {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.node-details {
  position: absolute;
  right: 20px;
  top: 80px;
  background: white;
  padding: 15px;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 100;
  max-width: 300px;
}

.detail-row {
  margin: 8px 0;
  display: flex;
}

.label {
  font-weight: bold;
  margin-right: 10px;
  min-width: 80px;
}

.approvers {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

/* 确保箭头可见 */
#arrowhead path {
  stroke: none;
}

/* 确保箭头可见 */
[class^="arrowhead-"] path {
  stroke: none;
}

/* 调整箭头位置 */
[class^="arrowhead-"] {
  marker-start: none;
}

</style>